package org.jeecg.modules.iot.util;

import com.aliyun.iot20180120.Client;
import com.aliyun.teaopenapi.models.Config;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.iot.model.v20180120.BatchGetDeviceStateRequest;
import com.aliyuncs.iot.model.v20180120.BatchGetDeviceStateResponse;
import com.aliyuncs.iot.model.v20180120.PubRequest;
import com.aliyuncs.iot.model.v20180120.PubResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.iot.aliyun.DeviceOnline;
import org.jeecg.modules.iot.aliyun.MessageBody;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.codec.binary.Base64.encodeBase64String;

/**
 * 阿里云物联网client
 *
 * @author scw
 * @version v1.0
 * @date
 */
@Configuration
public class IotClientUtil {

    @Value("${iot.accessKeyId}")
    private String accessKeyId;
    @Value("${iot.accessKeySecret}")
    private String accessKeySecret;
    @Value("${iot.regionId}")
    private String regionId;
    @Value("${iot.productKey}")
    private String productKey;
    @Value("${iot.iotInstanceId}")
    private String iotInstanceId;
    @Value("${iot.mnsEndpoint}")
    private String mnsEndpoint;

    private DefaultAcsClient defaultAcsClient;
    private Client client;

    @Bean
    public void initClient() throws Exception {
        Config config = new Config();
        // 您的AccessKey ID
        config.accessKeyId = accessKeyId;
        // 您的AccessKey Secret
        config.accessKeySecret = accessKeySecret;
        // 您的可用区ID
        config.regionId = regionId;

        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        this.defaultAcsClient = new DefaultAcsClient(profile);
    }

    @Bean
    public void initNewClient() throws Exception {
        Config config = new Config();
        // 您的AccessKey ID
        config.accessKeyId = accessKeyId;
        // 您的AccessKey Secret
        config.accessKeySecret = accessKeySecret;
        // 您的可用区ID
        config.regionId = regionId;
        this.client = new Client(config);
    }
    /**
     * getDeviceStatusList
     * @param productKey
     * @param deviceName
     * @return
     * @throws ClientException
     */
    public DeviceOnline getDeviceStatus(String productKey, String deviceName) throws ClientException {
        DeviceOnline online = DeviceOnline.NO_DEVICE;
        Map<String, DeviceOnline> map = getDeviceStatusMap(productKey, deviceName);
        if (map.size() > 0) {
            return map.get(deviceName);
        }
        return online;
    }
    /**
     * 发送异步消息
     */
    public PubResponse sendMsgAsync(String productKey, String topicFullName, String messageContent, int qos) throws ClientException {
        byte[] bytes = messageContent.getBytes(StandardCharsets.UTF_8);
        PubResponse response = sendMsgAsync(productKey, topicFullName, bytes, qos);
        return response;
    }

    /**
     * 发送异步消息
     */
    public PubResponse sendMsgAsync(String productKey, String topicFullName, byte[] bytes, int qos) throws ClientException {
        PubRequest request = new PubRequest();

        String base64 = encodeBase64String(bytes);

        request.setProductKey(productKey);
        request.setMessageContent(base64);
        request.setTopicFullName(topicFullName);

        request.setQos(qos > 1 ? 1 : qos); //目前支持QoS0和QoS1

        PubResponse response = this.defaultAcsClient.getAcsResponse(request);

        //TEST
        /**
         * 此处消息存放在redis中，不知其用意
         */
//        MessageBody messageBody = new MessageBody();
//        messageBody.setMessageId("send_message");
//        messageBody.setMessageType("send");
//        messageBody.setTopic(topicFullName);
//        messageBody.setPayload(new String(bytes, StandardCharsets.UTF_8));
//        messageBody.setTimestamp(System.currentTimeMillis() / 1000);
//        mnsUtils.putMessageBody(messageBody);

        return response;
    }


    /**
     * getDeviceStatusList
     * @param productKey
     * @param deviceNames
     * @return
     * @throws ClientException
     */
    public Map<String, DeviceOnline> getDeviceStatusMap(String productKey, String... deviceNames) throws ClientException{
        Map<String, DeviceOnline> map = new LinkedHashMap<String, DeviceOnline>();

        BatchGetDeviceStateRequest request = new BatchGetDeviceStateRequest();
        request.setProductKey(productKey);

        List<String> devices = new ArrayList<String>();
        for (String deviceName : deviceNames) {
            if(!StringUtils.isBlank(deviceName)){
                devices.add(deviceName);
                map.put(deviceName, DeviceOnline.NO_DEVICE);
            }
        }
        if(devices.size() == 0){
            return map;
        }
        request.setDeviceNames(devices);

        BatchGetDeviceStateResponse response = defaultAcsClient.getAcsResponse(request);
        List<BatchGetDeviceStateResponse.DeviceStatus> data = response.getDeviceStatusList();

        for(String key : map.keySet()){
            for(BatchGetDeviceStateResponse.DeviceStatus deviceStatus : data) {
                if (key.equals(deviceStatus.getDeviceName())) {
                    DeviceOnline online = DeviceOnline.getByName(deviceStatus.getStatus());
                    map.put(key, online);
                    break;
                }
            }
        }

        return map;
    }

    public DefaultAcsClient getDefaultAcsClient() {
        return defaultAcsClient;
    }

    public Client getClient() {
        return client;
    }

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public String getRegionId() {
        return regionId;
    }

    public String getProductKey() {
        return productKey;
    }

    public String getIotInstanceId() {
        return iotInstanceId;
    }

    public String getMnsEndpoint() {
        return mnsEndpoint;
    }
}
